#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rle.h"


int main(int argc, char *argv[])
{
    FILE *fpi,*fpo;
    unsigned char *pi,*po;
    long ni,no;
    int operation = 0;//0:encode(default),1:decode,2:get encoded file length,3:get decoded file length
    int bit_width = 8;//default
    int i;
    unsigned int (*fplength)(unsigned char *iptr,unsigned int ilen);
    unsigned int (*fpcodec)(unsigned char *iptr,unsigned int ilen,unsigned char *optr,unsigned int olen);

    fpi = fpo = NULL;
    if(argc < 3)
    {
        printf("使用游程编码(Running length encoding)的二值图像压缩和解压\n");
        printf("用法：\n");
        printf("4bit编码 %s -e -4 -o 输出文件 输入文件\n", argv[0]);
        printf("8bit编码 %s -e -8 -o 输出文件 输入文件\n", argv[0]);
        printf("4bit解码 %s -d -4 -o 输出文件 输入文件\n", argv[0]);
        printf("8bit解码 %s -d -8 -o 输出文件 输入文件\n", argv[0]);
        printf("显示4bit编码后的文件大小 %s -4 -n 输入文件\n", argv[0]);
        printf("显示8bit编码后的文件大小 %s -8 -n 输入文件\n", argv[0]);
        printf("显示4bit解码后的文件大小 %s -4 -u 输入文件\n", argv[0]);
        printf("显示8bit解码后的文件大小 %s -8 -u 输入文件\n", argv[0]);
        printf("注意：\n");
        printf("若不指定编码位宽，默认使用8bit编码。\n");
        return 0;
    }
    i = 1;
    while(i<argc)
    {
        if(strcmp(argv[i],"-o")==0)
        {
            i++;
            if(i<argc)
            {
                fpo = fopen(argv[i],"wb");
            }
        }
        else if(strcmp(argv[i],"-4")==0)
        {
            bit_width = 4;
        }
        else if(strcmp(argv[i],"-8")==0)
        {
            bit_width = 8;
        }
        else if(strcmp(argv[i],"-e")==0)
        {
            operation = 0;
        }
        else if(strcmp(argv[i],"-d")==0)
        {
            operation = 1;
        }
        else if(strcmp(argv[i],"-n")==0)
        {
            operation = 2;
        }
        else if(strcmp(argv[i],"-u")==0)
        {
            operation = 3;
        }
        else
        {
            fpi = fopen(argv[i],"rb");
            if(fpi)
            {
                fseek(fpi,0,SEEK_END);
                ni = ftell(fpi);
                fseek(fpi,0,SEEK_SET);
                if(ni>0)
                {
                    pi = malloc(ni);
                    if(!pi)
                    {
                        printf("为输入文件申请内存出错！\n");
                        return 0;
                    }
                    if(!fread(pi,ni,1,fpi))
                    {
                        printf("读输入文件内容出错！\n");
                    }
                    fclose(fpi);
                }
                else
                {
                    printf("出错了！输入文件是空的。\n");
                    return 0;
                }
            }
        }
        i++;
    }

    if(bit_width==8)
    {
        if((operation==0)||(operation==2))
        {
            fplength = rle8_encode_length;
            fpcodec = rle8_encode;
        }
        else
        {
            fplength = rle8_decode_length;
            fpcodec = rle8_decode;
        }
    }
    else
    {
        if((operation==0)||(operation==2))
        {
            fplength = rle4_encode_length;
            fpcodec = rle4_encode;
        }
        else
        {
            fplength = rle4_decode_length;
            fpcodec = rle4_decode;
        }
    }

    if(operation < 2)//编码,解码
    {
        no = fplength(pi,ni);
        if(no)
        {
            po = malloc(no);
            if(po)
            {
                if(fpcodec(pi,ni,po,no) > 0)
                {
                    fwrite(po,no,1,fpo);
                    fclose(fpo);
                }
            }
            else
            {
                printf("为输出文件申请内存出错！\n");
            }
        }
        free(pi);
    }
    else//显示编码解码后的文件大小
    {
        no = fplength(pi,ni);
        printf("%u",no);
        free(pi);
    }
    return 0;
}
